const { hash, compare } = require('bcryptjs')
const { sign } = require('jsonwebtoken')
const { isMobilePhone } = require('validator')
const fetch = require('node-fetch')

const { SignupError, getOpenid } = require('../../utils')

const auth = {
  signup: async (parent, { password, phone, openid: code, ...others }, ctx) => {
    // 存在 openid 是 wx.login 返回的 code, 需要通过 CODE_2_SESSION 转换
    const openid = await getOpenid(code)
    if (!isMobilePhone(phone, 'zh-CN')) {
      throw new SignupError('Phone number format error')
    }
    if (!password) {
      throw new SignupError('Password required')
    }
    if (password.length < 6) {
      throw new SignupError('Password length requires 6')
    }
    const hashedPassword = await hash(password, 10)
    const user = await ctx.db.mutation.createUser(
      {
        ...others,
        phone,
        openid,
        password: hashedPassword
      },
      info
    )

    return {
      token: sign({ userId: user.id }, process.env.APP_SECRET),
      user
    }
  },
  login: async (parent, { phone, password, openid: code }, ctx, info) => {
    let user

    if (phone && password) {
      user = await ctx.db.query.user({ phone }, info)

      if (!user) {
        throw new Error(`No user found for phone: ${phone}`)
      }

      const valid = await compare(password, user.password)
      if (!valid) {
        throw new Error('Invalid password')
      }
    }

    if (code) {
      const openid = await getOpenid(code)
      const users = await ctx.db.users({
        where: {
          openid
        }
      })

      if (!users || users.length === 0) {
        throw new Error(`No user found for openid: ${openid}`)
      }

      user = users[0]
    }

    return {
      token: sign({ userId: user.id }, process.env.APP_SECRET),
      user
    }
  }
}

module.exports = { auth }
